/*
 * Indiana University Community Grid Computing Lab Software License,Version 1.1
 *
 * Copyright (c) 2002 Community Grid Computing Lab, Indiana University.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *      "This product includes software developed by the Indiana University
 *       Community Grid Computing Lab (http://www.communitygrids.iu.edu/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Indiana Univeristy","Indiana Univeristy Pervasive Techonology
 *    Labs" and  "Indiana Univeristy Community Grid Computing Lab" must not be
 *    used to endorse or promote products derived from this software without
 *    prior written permission. For written permission, please contact
 *    http://www.communitygrids.iu.edu/.
 *
 * 5. Products derived from this software may not use "Indiana
 *    University" name nor may "Indiana University" appear in their name,
 *    without prior written permission of the Indiana University.
 *
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
 * INDIANA UNIVERSITY OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package cgl.sensorgrid.sopac.gps.filters;

import java.io.*;
import java.text.*;
import java.util.*;

import cgl.narada.event.*;
import cgl.sensorgrid.common.*;
import cgl.sensorgrid.filters.*;
import cgl.sensorgrid.hpsearch.*;

/**
 *
 * <p>Title: SensorGrid</p>
 *
 * <p>Description: </p>
 *
 * <p>Copyright: Copyright (c) 2006</p>
 *
 * <p>Company: </p>
 *
 * @author Galip Aydin
 * @version 1.0
 */
public class RdahmmFilter extends Filter {
    public RdahmmFilter() {
    }

    private String filePath;
    private String siteName;
    private String rdahmmDir;
    private FileWriter fw;
    private static boolean training = false;
    private int noOfObservations;
    private java.util.Properties properties = new java.util.Properties();
    static int runcount = 0;

    public RdahmmFilter(String[] argsa, String[] argsb) {
        try {
            loadProperties();
            rdahmmDir = properties.getProperty(
                    "rdahmm.eval.directory");
            System.out.println(
                    "[RdahmmFilter] --> Rdahmm Application Directory = " +
                    rdahmmDir);
            if (argsa == null || argsa.length == 0) {
                System.err.println(
                        "Incorrect number of arguments in RdahmmFilter::Constructor...");
                System.exit(0);
            } else {
                this.initialize(argsa);
            }

            if (argsb == null || argsa.length < 3) {
                System.err.println(
                        "Incorrect number of filter specific arguments in RdahmmFilter::Constructor...");
                System.exit(0);
            } else {
                if (argsb[0] != null && !argsb[0].equals("") &&
                    argsb[1] != null && !argsb[1].equals("") &&
                    argsb[2] != null && !argsb[2].equals("")) {
                    siteName = argsb[0];
                    noOfObservations = Integer.parseInt(argsb[1]);
                    String mode = argsb[2];
                    String baseDir = properties.getProperty(
                            "rdahmm.data.directory");
                    System.out.println(
                            "[RdahmmFilter] --> Rdahmm Data Directory = " +
                            baseDir);
                    File f = new File(baseDir);
                    if (!f.exists()) {
                        f.mkdir();
                    }

                    f = new File(baseDir + "/" + siteName);
                    if (!f.exists()) {
                        f.mkdirs();
                    }

                    if (mode.equalsIgnoreCase("training")) {
                        training = true;
                        filePath = baseDir + "/" + siteName + "/" + siteName +
                                   ".xyz";
                    }

                    else {
                        filePath = baseDir + "/" +
                                   siteName + "/" + siteName + "-" +
                                   getDate(System.currentTimeMillis()) +
                                   ".xyz";
                    }

                    System.out.println("[RdahmmFilter] --> Rdahmm Data File = " +
                                       filePath);
                    f = new File(filePath);
                    if (!f.exists()) {
                        f.createNewFile();
                    }
                    fw = new FileWriter(f);
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    /**
     *
     * @return Properties
     */
    private java.util.Properties loadProperties() {
        // Read properties file.
        try {
            properties = PropertyFile.loadProperties(
                    "sensorgrid.properties");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return properties;
    }


    /**
     *
     * @param GPS_week String
     * @param GPS_millisecond String
     * @return String
     */
    public String getDate(long timeinms) {
        try {
            Calendar cal = Calendar.getInstance();
            cal.setTimeInMillis(timeinms);
            SimpleDateFormat myDateFormat =
                    new SimpleDateFormat("yyyy_MM_dd-hh_mm_ss_a");
            return myDateFormat.format(cal.getTime());
        } catch (Exception ex) {
            ex.printStackTrace();
            return null;
        }
    }

    /**
     *
     * @param nbEvent NBEvent
     */
    public static int count = 0;

    public void onEvent(NBEvent nbEvent) {
        if (nbEvent.getContentPayload() != null) {
            //String fPath = filePath;
            File f = new File(filePath);
            String fileParent = f.getParent();
            try {
                if (nbEvent != null) {
                    String line = new String(nbEvent.getContentPayload());
                    //System.out.println("RDAHMM -- > " + line);
                    if (line.trim().endsWith("EOF")) {
                        line = line.substring(0, line.length() - 4);
                    }
                    StringTokenizer st = new StringTokenizer(line, "\t");
                    int tokcnt = 0;
                    String fileLine = "";
                    while (st.hasMoreTokens()) {
                        String token = st.nextToken();

                        if (tokcnt >= 3 && tokcnt < 6) {
                            fileLine += token.trim() + "\t";
                        }
                        tokcnt++;
                    }
                    //System.out.println(fileLine);
                    fw.write(fileLine + "\n");
                    fw.flush();
                    count++;

                    if (training) {
                        //System.out.print(count + " ");
                        if (count >= noOfObservations) {
                            filePath = fileParent + "/" + siteName + ".xyz";
                            System.out.println("fpath = " + filePath);
                            //trainRdahmm(fPath);
                            System.exit(0);
                        }
                    } else {
                        System.out.print(count + " ");
                        if (count >= noOfObservations) {
                            System.out.print("");
                            //invoke rdahmm here
                            //filePath = fPath;
//                            rdahmmEvaluate(filePath);
                            runRDAHMM(filePath, count);
                            // File f  =new File(filePath);

                            filePath = fileParent + "/" + siteName +
                                       "-" +
                                       getDate(System.currentTimeMillis()) +
                                       ".xyz";
                            //restart the file
                            fw.flush();
                            fw.close();
                            fw = new FileWriter(filePath);
                            count = 0;
                        }
                    }
                }
            } catch (Exception ex3) {
                ex3.printStackTrace();
            }
        }
    }


    public void runRDAHMM(String filePath, int lineCount) {
        System.out.println("[RdahmmFilter] --> Rdahmm Call # " + runcount);
        RunRdahmm run = new RunRdahmm();
        long a = System.currentTimeMillis();
        run.runRDAHMM(filePath, siteName, rdahmmDir, lineCount, runcount);
        System.out.println("[RdahmmFilter] --> RDAHMM coompleted in " +
                           (System.currentTimeMillis() - a) + " ms.");
        runcount++;
    }


    public void trainRdahmm(String filePath) {
        String command =
                "/home/gaydin/RDAHMM/rdahmm/bin/rdahmm " +
                "-data " + filePath +
                " -T " + noOfObservations +
                " -D 3 -N 4 -output_type gauss" +
                " -A " + filePath + "_snippet.A" +
                " -B " + filePath + "_snippet.B" +
                " -pi " + filePath + "_snippet.pi" +
                " -minvalfile " + filePath + "_snippet.minval" +
                " -maxvalfile " + filePath + "_snippet.maxval" +
                " -rangefile " + filePath + "_snippet.range" +
                " -Q " + filePath + "_snippet.Q" +
                " -anneal -annealstep 0.01 -regularize -omega 0 0 10 1.0e-6 -seed 1 -v";
        System.out.println(command);
    }


    /**
     *
     *
     * @param filePath String
     */
    public void rdahmmEvaluate(String filePath) {
        System.out.println("RDAHMM CALL # = " + runcount);
        try {
            System.out.println(filePath);
            StartScript s = new StartScript();
            s.startScript(siteName,
                          "file://" + filePath, runcount);
            runcount++;
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }


    /**
     * @param args  No arguments are used.
     */
    public static void main(String args[]) {
        if (args.length < 7) {
            System.out.println("Usage: java cgl.sensorgrid.sopac.gps.filters.RdahmmFilter commType nbHost nbPort subTopic siteName noOfObservations rdahmmMode");
            System.exit(0);
        }

        String commType = args[0];
        String nbHost = args[1];
        String nbPort = args[2];
        String subTopic = args[3];
        String siteName = args[4];
        String noOfObservations = args[5];
        String rdahmmMode = args[6];

//        String commType = "niotcp";
//        String nbHost = "gf2.ucs.indiana.edu";
//        String nbPort = "3344";
//        String subTopic = "/SOPAC/GPS/CRTN_01/POS/RAAP";
//        String siteName = "RAAP";
//        String noOfObservations = "10";
//        String rdahmmMode = "evaluation";

        String[] argsa = {commType,
                         nbHost,
                         nbPort,
                         subTopic,
                         ""};

        String[] argsb = {siteName, noOfObservations, rdahmmMode};
        RdahmmFilter test = new RdahmmFilter(argsa, argsb);
    }
}


class RunRdahmm extends Thread {

    public RunRdahmm() {
    }

    /**
     *
     *
     * @param filePath String
     */
    public void runRDAHMM(String filePath, String siteName, String evalDir,
                          int lineCount, int runcount) {
//        System.out.println("[RdahmmFilter] --> Rdahmm Call # " + runcount);
        try {
//            System.out.println("[RdahmmFilter] --> Rdahmm Data File = " +
//                               filePath);
            String stationName = siteName;
            int runNumber = runcount;
            String command = "";
            Runtime rt = Runtime.getRuntime();

            //First Go to the Directory where rdahmrunner.sh runs
//            try {
//                command = "cd " + evalDir;
//                System.out.println("[RdahmmFilter] --> Executing : " + command);
//                Process p = rt.exec("cd " + evalDir);
//                p.waitFor();
//                p.destroy();
//            } catch (Exception ex) {
//                ex.printStackTrace();
//            }

            //Copy Accumulated data File to Rdahmm Dir
            try {
                command = "cp " + filePath + " " +
                          evalDir + "/" + stationName + "/" + stationName +
                          "_" + runNumber + ".xyz ";
                System.out.println("[RdahmmFilter] --> Copying file : " + command);
                Process p = rt.exec("cp " + filePath + " " +
                                    evalDir + "/" + stationName + "/" +
                                    stationName + "_" +
                                    runNumber +
                                    ".xyz");
                p.waitFor();
                p.destroy();
                sleep(3);
            } catch (Exception ex) {
                ex.printStackTrace();
            }

            try {
                command = "./rdahmmrunner.sh " + stationName + " " +
                          lineCount + " " + runNumber;

                System.out.println("[RdahmmFilter] --> Executing : " + command);
                Process p = rt.exec("./rdahmmrunner.sh " + stationName + " " + lineCount + " " + runNumber);
//                p.waitFor();
//                p.destroy();
            } catch (Exception eio) {
                System.out.println("Error: " + eio);
                return;
            }
            runcount++;
        } catch (Exception ex) {
            //ex.printStackTrace();
        }
    }
}
